# -*- coding: UTF-8 -*-
__author__ = 'czyigy'
import struct
import binascii
from constant import *
from logger import logger
import traceback

class PackSendData():
    def __init__(self):
        self.buffer = []

    def Reverse(self,Src):
        Desc =''
        for item in Src:
            Desc = item + Desc
        return Desc



    def EncodeTimeType(self,Value):
        return self.Reverse(struct.pack('B', Value))

    def EncodeTimeStart(self,Value):
        return self.Reverse(struct.pack('H',Value))

    def EncodeTimeEnd(self,Value):
        return self.Reverse(struct.pack('H',Value))

    def EncodeTimeDuration(self,Value):
        return self.Reverse(struct.pack('H',Value))

    def EncodePatrolCmd(self,Value):
        return self.Reverse(struct.pack('B', Value))

    def EncodePatrolInterval(self,Value):
        return self.Reverse(struct.pack('B', Value))

    def EncodeElectricQuantity(self,Value):
        return self.Reverse(struct.pack('I',Value))

    def EncodeBatteryVoltage(self,Value):
        return self.Reverse(struct.pack('H',Value))

    def EncodeChargeTime(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeTemperateCompensation(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EndcodeTemperate(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeElectricity(self,Value):
        return self.Reverse(struct.pack('H',Value))

    def EncodeWorkMode(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeWorkTime(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeWorkPower(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodePowerControl(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeLightType(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeFactoryDefault(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodePolicyType(self,Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodePolicyTime(self,Value):
        return self.Reverse(struct.pack('I',Value))[1:3]


    def EncodeSwitchCmd(self, Value):
        return self.Reverse(struct.pack('B',Value))

    def EncodeDimCmd(self,Value):
        return self.Reverse(struct.pack('B',Value))

    #开关灯时间设置
    def EncodeSwitchTimeCmd(self,Values = []):
        Dest = ''
        Dest += self.EncodeTimeType(Values[0])
        Dest += self.EncodeTimeStart(Values[1])
        Dest += self.EncodeTimeEnd(Values[2])
        Dest += self.EncodeTimeDuration(Values[3])
        return Dest

    #自动巡检功能
    def EncodeAutoPatrolCmd(self,Values):
        Dest = ''
        Dest += self.EncodePatrolCmd(Values[0])
        Dest += self.EncodePatrolInterval(Values[1])
        return Dest

    #自动巡检功能
    def EncodeBatteryParam(self, Values):
        Dest = ''
        for value in Values[0:10]:
            Dest += self.EncodeBatteryVoltage(value)
        for value in Values[10:16]:
            if value < 0:
                Dest += self.Reverse(struct.pack('b', -128-value))
            else:
                Dest += self.Reverse(struct.pack('B', value))
        Dest += self.EncodeElectricity(Values[16])
        if len(Values) > 17:
            for value in Values[17:21]:
                if value < 0:
                    Dest += self.Reverse(struct.pack('b', -128-value))
                else:
                    Dest += self.Reverse(struct.pack('B', value))
        return Dest

    #负载参数设置
    def EncodeLoadParam(self,Values):
        Dest = ''
        for value in Values[0:9]:
            Dest += self.Reverse(struct.pack('B', value))
        Dest += self.EncodeWorkTime(Values[10])
        Dest += self.EncodeBatteryVoltage(Values[9])
        Dest += self.EncodeElectricity(Values[11])
        for value in Values[12:14]:
            Dest += self.Reverse(struct.pack('B', value))
        return Dest

    #策略下发设置
    def EncodePolicyCmd(self,Values):
        Dest = ''
        for i, value in enumerate(Values):
            if i%2 == 0:
                Dest += self.EncodePolicyType(value)
            else:
                Dest += self.EncodePolicyTime(value)
        return Dest

    #change channel cnd
    def EncodeChangeChannelCmd(self,Values):
        Dest = ''
        Dest += self.Reverse(struct.pack('B', Values[0]))
        Dest += self.Reverse(struct.pack('H', Values[1]))

        return Dest

    def EncodeQueryAllCompleteCmd(self, Addr, code, pdu, values):
        '''
        获取所有信息接口
        :param Addr:
        :param code:
        :param pdu:
        :param values:
        :return:
        '''
        try:
            if set(str(Addr))| ISHEXSET != ISHEXSET:
                return ''
            int_addr = int(Addr, 16)
            int_addr &= 0xffffffff
            senddata = self.Reverse(struct.pack('I', int_addr))
            senddata += self.Reverse(struct.pack('B', code))
            str_pdu = self.Reverse(struct.pack('H', pdu))
            senddata += str_pdu
            read_length = 70
            senddata += self.Reverse(struct.pack('B', read_length))
            check_code = 0
            str_check_code = str_pdu + self.Reverse(struct.pack('B', read_length))
            for data in str_check_code:
                check_code += struct.unpack('B', data)[0]
            check_code = struct.pack('I', check_code)[0]
            senddata += check_code
        except:
            logger.error(traceback.format_exc())
            senddata = ''
        return senddata

    def EncodeCompleteCmd(self, Addr, code, pdu, values):
        try:
            if set(str(Addr))| ISHEXSET != ISHEXSET:
                return ''
            int_addr = int(Addr, 16)
            int_addr &= 0xffffffff
            senddata = self.Reverse(struct.pack('I', int_addr))
            senddata += self.Reverse(struct.pack('B', code))
            str_pdu = self.Reverse(struct.pack('H', pdu))
            senddata += str_pdu
            if code == 16:
                value_str = ''
                if pdu == 784:
                    value_str = self.EncodeChangeChannelCmd(values)

                elif pdu == 800:
                    value_str = self.EncodeAutoPatrolCmd(values)

                elif pdu == 808:
                    value_str = self.EncodeBatteryParam(values)

                elif pdu == 1024:
                    value_str = self.EncodeLoadParam(values)

                elif pdu == 1128:
                    value_str = self.EncodePolicyCmd(values)

                str_len = self.Reverse(struct.pack('B', len(value_str)))
                senddata += (str_len + value_str)

                check_code = 0
                str_check_code = str_pdu + str_len + value_str
                for data in str_check_code:
                    check_code += struct.unpack('B', data)[0]
                check_code = struct.pack('I', check_code)[0]
                senddata += check_code
            elif code == 3:
                read_length = get_read_length(str_pdu)
                senddata += self.Reverse(struct.pack('B', read_length))
                check_code = 0
                str_check_code = str_pdu + self.Reverse(struct.pack('B', read_length))
                for data in str_check_code:
                    check_code += struct.unpack('B', data)[0]
                check_code = struct.pack('I', check_code)[0]
                senddata += check_code
            else:
                senddata += self.Reverse(struct.pack('B', values[0]))
                check_code = 0
                str_check_code = str_pdu + self.Reverse(struct.pack('B', values[0]))
                for data in str_check_code:
                    check_code += struct.unpack('B', data)[0]
                check_code = struct.pack('I', check_code)[0]
                senddata += check_code
        except:
            logger.error(traceback.format_exc())
            senddata = ''
        return senddata

    @classmethod
    def EncodeLorawanPatrolCmd(cls, strAddr, code, pdu):
        try:
            if set(str(strAddr))| ISHEXSET != ISHEXSET:
                return ''
            int_addr = int(strAddr, 16)
            int_addr &= 0xffffffff
            senddata = cls().Reverse(struct.pack('I', int_addr))
            senddata += cls().Reverse(struct.pack('B', code))
            str_pdu = cls().Reverse(struct.pack('H', pdu))
            senddata += str_pdu
            values = 0
            senddata += cls().Reverse(struct.pack('B', values))
            check_code = 0
            str_check_code = str_pdu + cls().Reverse(struct.pack('B', values))
            for data in str_check_code:
                check_code += struct.unpack('B', data)[0]
            check_code = struct.pack('I', check_code)[0]
            senddata += check_code
        except:
            logger.error(traceback.format_exc())
            senddata = ''
        return senddata
